package com.smart.common.utils;

import java.io.*;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipUtil {

    private static final int BUFFER_SIZE = 4096;


    public static void zip(String sourceFileName, String zipFileName) throws Exception {
        //File zipFile = new File(zipFileName);
        System.out.println("压缩中...");

        //创建zip输出流
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));

        //创建缓冲输出流
        BufferedOutputStream bos = new BufferedOutputStream(out);

        File sourceFile = new File(sourceFileName);

        //调用函数
        compress(out, bos, sourceFile, sourceFile.getName());

        bos.close();
        out.close();
        System.out.println("压缩完成");

    }

    public static void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base) throws Exception {
        //如果路径为目录（文件夹）
        if (sourceFile.isDirectory()) {

            //取出文件夹中的文件（或子文件夹）
            File[] flist = sourceFile.listFiles();

            if (flist.length == 0)//如果文件夹为空，则只需在目的地zip文件中写入一个目录进入点
            {
                System.out.println(base + "/");
                out.putNextEntry(new ZipEntry(base + "/"));
            } else//如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
            {
                for (int i = 0; i < flist.length; i++) {
                    compress(out, bos, flist[i], base + "/" + flist[i].getName());
                }
            }
        } else//如果不是目录（文件夹），即为文件，则先写入目录进入点，之后将文件写入zip文件中
        {
            out.putNextEntry(new ZipEntry(base));
            FileInputStream fos = new FileInputStream(sourceFile);
            BufferedInputStream bis = new BufferedInputStream(fos);

            int tag;
            System.out.println(base);
            //将源文件写入到zip文件中
            while ((tag = bis.read()) != -1) {
                out.write(tag);
            }
            bis.close();
            fos.close();

        }
    }

    /**
     * 根据自定义压缩层级,将文件压缩到Entry,需要调用者自己关闭流
     * 适合将分散的文件打包到同一个zip
     */
    public static void zipFileEntry(ZipOutputStream zos,File file,String entryName) throws Exception {
        ZipEntry zipEntry = new ZipEntry(entryName);
        zos.putNextEntry(zipEntry);
        int len;
        FileInputStream in = new FileInputStream(file);
        byte[] buf = new byte[BUFFER_SIZE];
        while ((len = in.read(buf)) != -1) {
            zos.write(buf, 0, len);
        }
        zos.closeEntry();
        in.close();

    }

    /**
     * zip中创建层级目录,需要调用者自己关闭流
     */
    public static void zipDirEntry(ZipOutputStream zos,String dirName) throws Exception {
        ZipEntry zipEntry = new ZipEntry(dirName);
        zos.putNextEntry(zipEntry);
        zos.closeEntry();
    }

    public static void main(String[] args) throws  Exception{
        String tmpRcPdfPath = "F:\\cardc\\export\\tmp"  + File.separator +"aaa.pdf";
        String s1 = "F:\\cardc\\export\\tmp"  + File.separator +"s1.pdf";
        String s2 = "F:\\cardc\\export\\tmp"  + File.separator +"s2.pdf";
        String tmpDownloadPath = "F:\\cardc\\export\\tmp" + File.separator  +UUID.randomUUID()+"_download_tmp.zip";
        ZipOutputStream zos = null;
        FileOutputStream fileOutputStream = new FileOutputStream(new File(tmpDownloadPath));
        zos = new ZipOutputStream(fileOutputStream);
        File file = new File(tmpRcPdfPath);
        //将对账单打包到zip
        ZipUtil.zipFileEntry(zos, file, file.getName());
        String zipDirName = "明细/";
        ZipUtil.zipDirEntry(zos,zipDirName);
        File file1 = new File(s1);
        File file2 = new File(s2);
        ZipUtil.zipFileEntry(zos,file1,zipDirName+file1.getName());
        ZipUtil.zipFileEntry(zos,file2,zipDirName+file2.getName());

        zos.close();
    }
}